using System;
using System.Collections.Generic;
using UnityEngine.Serialization;
using UnityEngine.UI.Extensions.EasingCore;

namespace UnityEngine.UI.Extensions
{
    public class UIScrollView : FancyScrollView<UICellData, UIContextRect>
    {
        [SerializeField]
        private FancyScroller m_Scroller = default;
        [SerializeField]
        private GameObject m_CellPrefab = default;

        public Action<int> OnSelectionChanged;

        public FancyScroller Scroller
        {
            get
            {
                return m_Scroller;
            }
        }

        public override GameObject CellPrefab
        {
            get
            {
                return m_CellPrefab;
            }
        }

        protected override void Initialize()
        {
            base.Initialize();
            Scroller.OnValueChanged(UpdatePosition);
            Scroller.OnSelectionChanged(UpdateSelection);
        }

        private void UpdateSelection(int index)
        {
            CanSelection(index);
        }

        public void UpdateData(int count)
        {
            IList<UICellData> list = new List<UICellData>();

            for (int i = 0; i < count; i++)
            {
                list.Add(new UICellData(i));
            }

            UpdateData(list);
        }

        public void UpdateData(IList<UICellData> items)
        {
            UpdateContents(items);
            Scroller.SetTotalCount(items.Count);
        }

        public void ScrollTo(int index, float duration, Ease easing)
        {
            UpdateSelectionByScrollTo(index, duration, easing);
        }

        public void ScrollToNext()
        {
            UpdateSelectionByScrollTo(Context.SelectedIndex + 1, 0.35f, Ease.OutCubic);
        }

        public void ScrollToNext(float duration, Ease easing)
        {
            UpdateSelectionByScrollTo(Context.SelectedIndex + 1, duration, easing);
        }

        public void ScrollToPre()
        {
            UpdateSelectionByScrollTo(Context.SelectedIndex - 1, 0.35f, Ease.OutCubic);
        }

        public void ScrollToPre(float duration, Ease easing)
        {
            UpdateSelectionByScrollTo(Context.SelectedIndex - 1, duration, easing);
        }

        public void JumpTo(int index)
        {
            UpdateSelectionByJumpTo(index);
        }

        public void JumpToNext()
        {
            UpdateSelectionByJumpTo(Context.SelectedIndex + 1);
        }

        public void JumpToPre()
        {
            UpdateSelectionByJumpTo(Context.SelectedIndex - 1);
        }

        private void UpdateSelectionByScrollTo(int index, float duration, Ease easing)
        {
            if (CanSelection(index))
            {
                Scroller.ScrollTo(index, duration, easing);
            }
        }

        private void UpdateSelectionByJumpTo(int index)
        {
            if (CanSelection(index))
            {
                Scroller.JumpTo(index);
            }
        }

        private bool CanSelection(int index)
        {
            if (index < 0 || index >= ItemsSource.Count || index == Context.SelectedIndex)
            {
                return false;
            }

            Context.SelectedIndex = index;
            Refresh();
            OnSelectionChanged?.Invoke(index);

            return true;
        }
    }
}